home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Thread Manager / Thread Manager 2.1.1d1+ / ThreadedSort / Sprocket / Lib / DialogWindow.cp < prev    next >
Encoding:
Text File  |  1995-04-28  |  6.2 KB  |  229 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DialogWindow.cp
  3.  
  4.     Contains:    Implementation of a base class for Modeless Dialogs
  5.                 
  6.     Written by: Dave Falkenburg
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.          <7>    11/16/94    DRF        Added explicit #include <Traps.h> for latest universal headers.
  13.          <6>    11/12/94    DRF        Fix a bug in EventFilter method which returned false even if a
  14.                                     dialog item was hit.
  15.          <5>     11/8/94    DRF        We have better menu handling methods, so use them instead of the
  16.                                     old “DoEditMenu” method.
  17.          <3>    10/17/94    DRF         ItemHit is now a pure-virtual method. Fixed bugs in DoEditMenu.
  18.                                      Call StdFilterProc inside EventFilter to handle ok, cancel,
  19.                                     and I-beam cursor tracking.
  20.          <3>     9/27/94    DRF         AppLib.h is now Sprocket.h
  21.          <2>      9/9/94    DRF        Reordered headers and removed redundant #includes. Also fixed
  22.                                     constants in DoEditMenu.
  23.  */
  24.  
  25. #include "Sprocket.h"
  26. #include "DialogWindow.h"
  27. #include "StandardMenus.h"
  28. #include <Traps.h>
  29.  
  30. TDialogWindow::TDialogWindow(DialogTemplateID dialogTemplateID)
  31.     {
  32.     fTemplateID = dialogTemplateID;
  33.     this->CreateWindow(kNormalWindow);
  34.     }
  35.  
  36.  
  37. WindowPtr
  38. TDialogWindow::MakeNewWindow(WindowPtr behindWindow)
  39.     {
  40.     return GetNewDialog(fTemplateID,nil,behindWindow);
  41.     }
  42.  
  43.  
  44. ////////////////////////////////////////////////////////////////////////////////////
  45. //
  46. //    EventFilter strategy for Dialog Window
  47. //
  48. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  49. //    and DialogSelect, only do these things when a Modless Dialog is the frontmost
  50. //    window. (e.g., it’s event filter is active)
  51. //
  52. //    NOTE: We always pass events through, except when an item has been hit.
  53. //
  54. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  55. //    this program. You’re probably right.
  56.  
  57. pascal    WindowPtr    FrontWindowPatchForDialogs();
  58.  
  59.  
  60. pascal    WindowPtr
  61. FrontWindowPatchForDialogs()
  62.     {
  63.     return FrontNonFloatingWindow();
  64.     }
  65.  
  66. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowPtr))))
  67.  
  68. UniversalProcPtr FrontWindowPatchUPP
  69. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  70.  
  71.  
  72. Boolean
  73. TDialogWindow::EventFilter(EventRecord *theEvent)
  74.     {
  75.     GrafPtr                oldPort;
  76.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  77.     DialogPtr            aDialog;
  78.     Boolean                eventHasBeenGobbled = false;
  79.     short                aDialogItem;
  80.     short                oldWindowKind;
  81.     
  82.     //    Don’t snarf keypresses meant for menus
  83.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  84.         return false;
  85.  
  86.     GetPort(&oldPort);
  87.     SetPort(fWindow);
  88.     
  89.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  90.     //    thing. DialogManager should check both frontmost floating and frontmost
  91.     //    non-floating windows, however we don’t support floating dialogs.
  92.     SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
  93.  
  94.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  95.     //    Dialog Manager can recognize our window as a dialog window.
  96.     oldWindowKind = ((WindowPeek) fWindow)->windowKind;
  97.     ((WindowPeek) fWindow)->windowKind = dialogKind;
  98.     
  99.     
  100.     if (IsDialogEvent(theEvent))
  101.         {
  102.         //    It’s definitely a dialog event, so let the DialogMgr figure things out.
  103.         //
  104.         //    We first let StdFilterProc have a crack at it so that the default
  105.         //    and cancel buttons are properly processed (as well as automagic text
  106.         //    cursor tracking).
  107.         
  108.         //    If StdFilterProc didn’t find anything to do, go ahead and call
  109.         //    DialogSelect to figure out if the user did anything important.
  110.  
  111.         //    Isn’t this alot easier than what Inside Mac says to do?
  112.  
  113.         eventHasBeenGobbled = StdFilterProc(fWindow,theEvent,&aDialogItem);
  114.         if (eventHasBeenGobbled == false)
  115.             eventHasBeenGobbled = DialogSelect(theEvent,&aDialog,&aDialogItem);
  116.         }
  117.  
  118.     //    Restore the windowKind
  119.     ((WindowPeek) fWindow)->windowKind = oldWindowKind;
  120.  
  121.     //    Put FrontWindow back the way it really belongs
  122.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
  123.  
  124.     if (eventHasBeenGobbled)
  125.         {
  126.         this->ItemHit(aDialogItem);    //    Call user’s method to deal with a hit
  127.         eventHasBeenGobbled = true;
  128.         }
  129.         
  130.     SetPort(oldPort);
  131.     
  132.     return eventHasBeenGobbled;
  133.     }
  134.  
  135.  
  136. void
  137. TDialogWindow::Activate(Boolean activating)
  138.     {
  139.     EventRecord            fakeEvent;
  140.  
  141.     /*    (De)activates are NOT automagically handled because our floating
  142.      *    windows prevent real activate events from ever being generated
  143.      *    for any non-floaters windows.
  144.      *
  145.      *    Our strategy is to fool the dialog manager into thinking that
  146.      *    things are still fine by passing it a fake (de)activate event.
  147.      *
  148.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  149.      *    work for activate and update events.
  150.      */
  151.         
  152.     OSEventAvail(0,&fakeEvent);        //    Get an intialized, but otherwise empty event record
  153.     
  154.     fakeEvent.what = activateEvt;
  155.     fakeEvent.message = (unsigned long) fWindow;
  156.     if (activating)
  157.         fakeEvent.modifiers |= activeFlag;
  158.     else
  159.         fakeEvent.modifiers &= ~activeFlag;
  160.  
  161.     //    Pass event on to DialogSelect
  162.     
  163.     DialogPtr    aDialog;
  164.     short        aDialogItem;
  165.     
  166.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  167.     }
  168.     
  169.  
  170. void
  171. TDialogWindow::Draw(void)
  172.     {
  173.     //    Automagically handled by Dialog Manager when we are
  174.     //    the frontmost window, but not at other times because
  175.     //    we only set the windowKind to dialogKind inside our
  176.     //    EventFilter (which is only active when we are frontmost).
  177.     
  178.     UpdateDialog((DialogPtr) fWindow, fWindow->visRgn);
  179.     }
  180.     
  181.     
  182. void
  183. TDialogWindow::Click(EventRecord * /* anEvent */)
  184.     {
  185.     /*    The only time this method is called is to handle a click
  186.      *    when the dialog window isn’t frontmost. All other times,
  187.      *    DialogSelect will do everything for us.
  188.      *
  189.      *    If our dialog contains useritems with the ability to
  190.      *    be the source of a drag we’d need to start drag tracking
  191.      *    in here.
  192.      */
  193.      
  194.     this->Select();
  195.     }
  196.  
  197.     
  198. void
  199. TDialogWindow::DoMenuSelection(short menu, short item)
  200.     {
  201.     if (menu == mEdit)
  202.         {
  203.         switch (item)
  204.             {
  205.             case    iUndo:
  206.                 break;
  207.                 
  208.             case    iCut:
  209.                 DialogCut(fWindow);
  210.                 return;
  211.                 
  212.             case    iCopy:
  213.                 DialogCopy(fWindow); 
  214.                 return;
  215.                 
  216.             case    iPaste:
  217.                 DialogPaste(fWindow); 
  218.                 return;
  219.                 
  220.             case    iClear:
  221.                 DialogDelete(fWindow); 
  222.                 return;
  223.             }
  224.         }
  225.     
  226.     //    Call through to inherited method
  227.     TWindow::DoMenuSelection(menu,item);
  228.     }
  229.